{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.utils.data as data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([-0.2088, -0.3393]), tensor([4.9463]))"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 我们定义目标为Y = Xw + b + ε\n",
    "# 先要生成训练用数据\n",
    "true_w = torch.tensor([[2], [-3.4]])\n",
    "true_b = 4.2\n",
    "\n",
    "X = torch.normal(0, 1, (1000, 2)) # 输入\n",
    "Y = X.matmul(true_w) + true_b\n",
    "Y += torch.normal(0, 0.01, Y.shape) # 带噪声的真实输出\n",
    "X[0], Y[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 同样的要实现随机挑选指定数量的样本\n",
    "def data_choose_batch(features, labels, batch_size):\n",
    "    dataset = data.TensorDataset(features,labels)\n",
    "    return data.DataLoader(dataset,batch_size,shuffle=True)\n",
    " \n",
    "batch_size = 10\n",
    "data_iter = data_choose_batch(X,Y,batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([0.])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 模型及权重初始化\n",
    "net = torch.nn.Sequential(torch.nn.Linear(2,1))\n",
    "net[0].weight.data.normal_(0,0.01)\n",
    "net[0].bias.data.fill_(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 损失函数和优化器\n",
    "loss = torch.nn.MSELoss()\n",
    "optim = torch.optim.SGD(net.parameters(),lr=0.03)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[epoch1]loss:0.00018445952446199954\n",
      "[epoch2]loss:9.266650886274874e-05\n",
      "[epoch3]loss:9.224876703228801e-05\n",
      "[epoch4]loss:9.20397651498206e-05\n",
      "[epoch5]loss:9.259046782972291e-05\n",
      "w误差：tensor([[-2.3544e-04, -5.3999e+00],\n",
      "        [ 5.3998e+00,  1.0014e-04]])\n",
      "b误差：tensor([0.0005])\n"
     ]
    }
   ],
   "source": [
    "# 训练\n",
    "num_epochs = 5\n",
    "for epoch in range(num_epochs):\n",
    "    for x, y in data_iter:\n",
    "        l = loss(net(x), y)\n",
    "        optim.zero_grad()\n",
    "        l.backward()\n",
    "        # print(net.weight.grad)\n",
    "        optim.step()\n",
    "    l = loss(net(X), Y)\n",
    "    print(f\"[epoch{epoch+1}]loss:{l}\")\n",
    "\n",
    "w = net[0].weight.data\n",
    "b = net[0].bias.data\n",
    "print(f'w误差：{w - true_w}')\n",
    "print(f'b误差：{b - true_b}')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
